package utils;

import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;

import javax.swing.JOptionPane;
import javax.swing.JTextField;

/**
 * Simple port scanner.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public final class PortScanner {

	public static final int CORRECT_PORT_VALUE		= 0;
	public static final int INCORRECT_PORT_NUMBER	= 1;
	public static final int INCORRECT_PORT_RANGE	= 2;
	public static final int PORT_IS_BUSY			= 4;
	
	
	private PortScanner() { }
	
	
	/**
	 * This method scans the port specified.
	 * @param portNumber - number of port to scan
	 * @return true, if the port is busy, otherwise false
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public static boolean scan(int portNumber) {
		
		try {
			Socket socket = new Socket("localhost", portNumber);
			socket.shutdownInput();
			socket.shutdownOutput();
			socket.close();
		}
		catch (ConnectException ce) {
			return false;
		}
		catch (IOException ioe) {
			return false;
		}
		
		return true;
	}
	
	
	
	/**
	 * Port validator.
	 * @param portField - text field which represents port field value
	 * @return
	 *  0 - correct port value <br>
	 *  1 - port value is not number <br>
	 *  2 - incorrect port range <br>
	 *  3 - port is busy
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public static int validate(JTextField portField) {
		
		String portString = portField.getText();
		int portNumber = -1;
		
		try {
			portNumber = Integer.parseInt( portString );
		}
		catch (NumberFormatException nfe) {
			return INCORRECT_PORT_NUMBER;
		}
		
		if (portNumber < 1025 || portNumber > 65535) {
			return INCORRECT_PORT_RANGE;
		}
		
		if ( PortScanner.scan(portNumber) ) {
			return PORT_IS_BUSY;
		}
		
		return CORRECT_PORT_VALUE;
	}
	
	
	/**
	 * This method validates port values and shows apropriate message.
	 * @param portField
	 * @param portName
	 * @return
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public static boolean validationWithInfo(JTextField portField, String portName) {
		int validationValue = PortScanner.validate(portField);
		String portValidationMessage = "";
		
		switch ( validationValue ) {
			case PortScanner.INCORRECT_PORT_NUMBER:
				portValidationMessage = "Incorrect port number. Port value must be a number.";
				break;
			case PortScanner.INCORRECT_PORT_RANGE:
				portValidationMessage = "Incorrect port range. Must be between 1025 and 65535.";
				break;
			case PortScanner.PORT_IS_BUSY:
				portValidationMessage = "Port is busy. Try another value.";
				break;
			case PortScanner.CORRECT_PORT_VALUE:
				break;
		}
		
		if (validationValue != PortScanner.CORRECT_PORT_VALUE) {
			JOptionPane.showMessageDialog(null, portValidationMessage, portName + " Error", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		
		return true;
	}
	
}
